package com.xianniu.ltc.service.impl;

import cn.devezhao.bizz.security.member.BusinessUnit;
import cn.devezhao.persist4j.engine.ID;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rebuild.core.Application;
import com.rebuild.core.configuration.general.ClassificationManager;
import com.rebuild.core.configuration.general.MultiSelectManager;
import com.rebuild.core.privileges.DepartmentService;
import com.rebuild.core.privileges.bizz.Department;
import com.xianniu.ltc.mapper.TRbhetong0Mapper;
import com.xianniu.ltc.model.entity.TRbhetong0DTO;
import com.xianniu.ltc.model.po.report.StatisticsByDeptPO;
import com.xianniu.ltc.service.ContractService;
import com.xxl.sso.core.entity.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: dingyx
 * @Date: 2022/4/7 3:10 下午
 */
@Slf4j
@Service
public class ContractServiceImpl implements ContractService {
    /**
     * 配置文件中我的qq邮箱
     */
    @Value("${report.contact.deptList}")
    private String deptListStr;

    @Resource
    private TRbhetong0Mapper tRbhetong0Mapper;
    @Override
    public Map<String, Map<String, TreeMap<String, Map<String, BigDecimal>>>> contractStatistics() {
        // 查询生效日期是今年的合同
        QueryWrapper<TRbhetong0DTO> query = new QueryWrapper<>();
        query.apply(" year(hetongshengxiaoriqi) = " + DateUtil.date().year());
        List<TRbhetong0DTO> contractOfThisYear = tRbhetong0Mapper.selectList(query);
        // 清洗合同数据
        cleanContractData(contractOfThisYear);
        Map<String, Map<String, TreeMap<String, Map<String, BigDecimal>>>> result = new HashMap<>();
        // A-统计总体数据
        result.put("total", staticsByTotal(contractOfThisYear));
        // B-按照部门分组统计数据
        result.put("dept", staticsByDepartment(contractOfThisYear));
        // C-按照业务类型跟交付模式
//        result.put("business", staticsByBusinessType(contractOfThisYear));
        return result;
    }

    @Override
    public Map<String, TreeMap<String, Map<String, BigDecimal>>> contractStatisticsByDept(StatisticsByDeptPO po) {
        String deptName = po.getDeptName();
        TreeMap<String, TreeMap<String, Map<String, BigDecimal>>> result = new TreeMap<>();
        // 查询生效日期是今年的合同
        QueryWrapper<TRbhetong0DTO> query = new QueryWrapper<>();
        query.apply(" year(hetongshengxiaoriqi) = " + DateUtil.date().year());
        List<TRbhetong0DTO> contractOfThisYear = tRbhetong0Mapper.selectList(query);
        // 清洗合同数据
        cleanContractData(contractOfThisYear);
        // 合同统计部门
        List<String> deptList = Arrays.asList(deptListStr.split(",")) ;
        // 如果没有选择部门或者选择的部门不是需要统计，则展示全部的部门数据
        if(StrUtil.isBlank(deptName) || !deptList.contains(deptName)){
            log.info("传入的部门名称是：{}, 无效参数。展示全部门签约数据", deptName);
            return staticsByDepartment(contractOfThisYear);
        }
        Department dept = getByDeptName(deptName);
        // 如果展选择的部门不存在，则展示非销售团队数据
        if(Objects.isNull(dept)){
            // 需要展示统计数据的部门
            List<BusinessUnit> businessUnits =  deptToShow();
            Set<BusinessUnit> buSet = new HashSet<>();
            businessUnits.forEach(bu -> {
                buSet.addAll(bu.getChildren());
                buSet.add(bu);
            });
            // 需要展示统计数据的部门ID集合
            List<String> buIDs = buSet.stream().map(bu -> bu.getIdentity().toString()).collect(Collectors.toList());
            log.info("需要展示的部门的所有部门ID合计是{}", buIDs);
            // 筛选需要展示的部门下的合同
            List<TRbhetong0DTO> contactOfDept = contractOfThisYear.stream().filter(c -> buIDs.contains(c.getOwningDept())).collect(Collectors.toList());
            // 剔除销售部门数据
            contractOfThisYear.removeAll(contactOfDept);
            List<TRbhetong0DTO> contactNotSale = contractOfThisYear;
            // 按照部门分组
            Map<String, List<TRbhetong0DTO>> deptGroup = contactNotSale.stream().collect(Collectors.groupingBy(TRbhetong0DTO::getOwningDeptName));
            for(Map.Entry<String, List<TRbhetong0DTO>> entry : deptGroup.entrySet()){
                TreeMap<String, Map<String, BigDecimal>> dataMap = abc(entry.getValue());
                result.put(entry.getKey(), dataMap);
            }
            log.info("需要展示的部门的所有部门合同编号合计是{}", contactNotSale.stream().map(TRbhetong0DTO::getHetongbianhao).collect(Collectors.toList()));
        }else{
            // 如果部门存在，则展示部门及子部门下的数据
            // 需要展示统计数据的部门
            Set<BusinessUnit> buSet =  dept.getAllChildrenModified();
            buSet.add(dept);
            // 需要展示统计数据的部门ID集合
            List<String> buIDs = buSet.stream().map(bu -> bu.getIdentity().toString()).collect(Collectors.toList());
            log.info("需要展示的部门的所有部门ID合计是{}", buIDs);
            // 筛选需要展示的部门下的合同
            List<TRbhetong0DTO> contactNotSale = contractOfThisYear.stream().filter(c -> buIDs.contains(c.getOwningDept())).collect(Collectors.toList());
            // 按照部门分组
            Map<String, List<TRbhetong0DTO>> deptGroup = contactNotSale.stream().collect(Collectors.groupingBy(TRbhetong0DTO::getOwningDeptName));
            for(Map.Entry<String, List<TRbhetong0DTO>> entry : deptGroup.entrySet()){
                TreeMap<String, Map<String, BigDecimal>> dataMap = abc(entry.getValue());
                result.put(entry.getKey(), dataMap);
            }
            log.info("需要展示的部门的所有部门合同编号合计是{}", contactNotSale.stream().map(TRbhetong0DTO::getHetongbianhao).collect(Collectors.toList()));
        }
        return result;
    }

    /**
     * 按照业务类型和交付模式拆分
     * @param contractOfThisYear
     */
    @Deprecated
    private Map<String, TreeMap<String, Map<String, BigDecimal>>> staticsByBusinessType(List<TRbhetong0DTO> contractOfThisYear) {
        // 合同按照是否是维保分组
        Map<Boolean, List<TRbhetong0DTO>> deptGroup = contractOfThisYear.stream().collect(Collectors.groupingBy(unit -> unit.getYewuleixing() == 1));
        Map<String, TreeMap<String, Map<String, BigDecimal>>> result = new HashMap<>();
        for(Map.Entry<Boolean, List<TRbhetong0DTO>> isMA : deptGroup.entrySet()){
            // 业务类型名称
            String yewuleixingName =  isMA.getKey() ? "维保服务合同" : "其他服务合同";
            TreeMap<String, Map<String, BigDecimal>> dataMap = new TreeMap<>();
            result.put(yewuleixingName, dataMap);
            // 合同数据
            List<TRbhetong0DTO> deptData = isMA.getValue();
            // 数据按照合同生效日期分组
            Map<Integer, List<TRbhetong0DTO>> monthGroup = deptData.stream().collect(Collectors.groupingBy(contract -> DateUtil.month(contract.getHetongshengxiaoriqi())));
            // 当前月份
            int currentMonth = DateUtil.month(new Date());
            for(int i = 0; i<= currentMonth; i++){
                // 显示月份
                int monthNo = i + 1;
                Map<String, BigDecimal> monthMap = new HashMap<>();
                // 判断按月份分组的数据集合中是否包含 i
                if(!monthGroup.containsKey(i)){
                    monthMap.put("amountOfBlend", BigDecimal.ZERO);
                    monthMap.put("amountOfResale", BigDecimal.ZERO);
                    monthMap.put("amountOfAutonomy", BigDecimal.ZERO);
                    dataMap.put(monthNo + "", monthMap);
                    continue;
                }
                // 部门月度合同数据
                List<TRbhetong0DTO> monthData = isMA.getValue();
                // 混合交付
                BigDecimal amountOfBlend = monthData.stream().filter(unit -> unit.getJuesedandangName().equals("拆包（混合交付）")).map(TRbhetong0DTO::getQianyuejineweishui).reduce(BigDecimal.ZERO, BigDecimal::add);
                // 整包交付
                BigDecimal amountOfResale = monthData.stream().filter(unit -> unit.getJuesedandangName().equals("整包（纯转售）")).map(TRbhetong0DTO::getQianyuejineweishui).reduce(BigDecimal.ZERO, BigDecimal::add);
                // 自主交付
                BigDecimal amountOfAutonomy = monthData.stream().filter(unit -> unit.getJuesedandangName().equals("自主（自交付）")).map(TRbhetong0DTO::getZizhuyeji).reduce(BigDecimal.ZERO, BigDecimal::add);

                monthMap.put("amountOfBlend", amountOfBlend);
                monthMap.put("amountOfResale", amountOfResale);
                monthMap.put("amountOfAutonomy", amountOfAutonomy);
                dataMap.put(monthNo + "", monthMap);
            }
        }
        return result;
    }

    /**
     * 补充合同的数据
     * @param contractOfThisYear
     */
    private void cleanContractData(List<TRbhetong0DTO> contractOfThisYear) {
        for(TRbhetong0DTO contract : contractOfThisYear){
            // 补充合同所属部门名称
            contract.setOwningDeptName(Application.getUserStore().getDepartment(ID.valueOf(contract.getOwningDept())).getName());
            // 补充合同的项目性质（自主/承接）
            contract.setJuesedandangName(ClassificationManager.instance.getName(ID.valueOf(contract.getJuesedandang())));
            // 补充合同的交付模式（拆包/整包/自主）
            contract.setJiaofumoshiName(ClassificationManager.instance.getName(ID.valueOf(contract.getJiaofumoshi())));
        }
    }

    /**
     * 按照部门分组统计合同数据
     * @param contractOfThisYear
     */
    private TreeMap<String, TreeMap<String, Map<String, BigDecimal>>> staticsByDepartment(List<TRbhetong0DTO> contractOfThisYear) {
        TreeMap<String, TreeMap<String, Map<String, BigDecimal>>> result = new TreeMap<>();
        if(StrUtil.isBlank(deptListStr)){
            log.info("合同统计的部门信息为空，不需要统计");
            return result;
        }
        // 非销售部门标示
        String deptNotSale = "非销售部门";
        // 临时数据
        List<TRbhetong0DTO> tmp = new ArrayList<>();
        // 部门名称分组
        List<String> deptList = Arrays.asList(deptListStr.split(",")) ;
        for(String deptName : deptList){
            Department parentBU = getByDeptName(deptName);
            if(Objects.nonNull(parentBU)){
                // 部门下的所有子部门
                Set<BusinessUnit> buSet = parentBU.getAllChildrenModified();
                buSet.add(parentBU);
                // 统计所有子部门ID集合
                List<String> buIDs = buSet.stream().map(bu -> bu.getIdentity().toString()).collect(Collectors.toList());
                log.info("{}下的所有子部门ID合计是{}", deptName, buIDs);
                // 筛选部门及子部门下的合同
                List<TRbhetong0DTO> contactOfDept = contractOfThisYear.stream().filter(c -> buIDs.contains(c.getOwningDept())).collect(Collectors.toList());
                log.info("{}下的所有合同编号合计是{}", deptName, contactOfDept.stream().map(TRbhetong0DTO::getHetongbianhao).collect(Collectors.toList()));
                // 统计部门合同数据
                TreeMap<String, Map<String, BigDecimal>> dataMap = abc(contactOfDept);
                result.put(deptName, dataMap);
                // 累加销售部门数据
                tmp.addAll(contactOfDept);
            }else{
                deptNotSale = deptName;
                log.info("{}->不存在这个部门", deptName);
            }
        }
        // 剔除销售部门数据
        contractOfThisYear.removeAll(tmp);
        List<TRbhetong0DTO> contactNotSale = contractOfThisYear;
        log.info("{}下的所有合同编号合计是{}", deptNotSale, contactNotSale.stream().map(TRbhetong0DTO::getHetongbianhao).collect(Collectors.toList()));
        TreeMap<String, Map<String, BigDecimal>> dataMap = abc(contactNotSale);
        result.put(deptNotSale, dataMap);
        return result;
    }

    /**
     * 统计部门数据
     * @param contactOfDept 合同数据
     * @return
     */
    private TreeMap<String, Map<String, BigDecimal>> abc(List<TRbhetong0DTO> contactOfDept) {
        TreeMap<String, Map<String, BigDecimal>> dataMap = new TreeMap<>();
        // 部门数据按照合同生效日期分组
        Map<Integer, List<TRbhetong0DTO>> monthGroup = contactOfDept.stream().collect(Collectors.groupingBy(contract -> DateUtil.month(contract.getHetongshengxiaoriqi())));
        // 当前月份
        int currentMonth = DateUtil.month(new Date());
        for(int i = 0; i<= currentMonth; i++){
            Map<String, BigDecimal> monthMap = new HashMap<>();
            // 显示月份
            int monthNo = i + 1;
            // 判断按月份分组的数据集合中是否包含 i
            if(!monthGroup.containsKey(i)){
                monthMap.put("amountOfSaleAutonomyWithoutTax", BigDecimal.ZERO);
                monthMap.put("amountOfSaleUndertakeWithoutTax", BigDecimal.ZERO);
                monthMap.put("totalAmountWithoutTax", BigDecimal.ZERO);
                dataMap.put(monthNo + "", monthMap);
                continue;
            }
            // 部门月度合同数据
            List<TRbhetong0DTO> monthData = monthGroup.get(i);
            // 自主签约额（未税）
            BigDecimal amountOfSaleAutonomyWithoutTax = monthData.stream().filter(unit -> unit.getJuesedandangName().equals("自主")).map(TRbhetong0DTO::getQianyuejineweishui).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 承接签约额（未税）
            BigDecimal amountOfSaleUndertakeWithoutTax = monthData.stream().filter(unit -> unit.getJuesedandangName().equals("承接")).map(TRbhetong0DTO::getQianyuejineweishui).reduce(BigDecimal.ZERO, BigDecimal::add);
            monthMap.put("amountOfSaleAutonomyWithoutTax", amountOfSaleAutonomyWithoutTax);
            monthMap.put("amountOfSaleUndertakeWithoutTax", amountOfSaleUndertakeWithoutTax);
            monthMap.put("totalAmountWithoutTax", NumberUtil.add(amountOfSaleAutonomyWithoutTax, amountOfSaleUndertakeWithoutTax));
            dataMap.put(monthNo + "", monthMap);
        }
        return dataMap;
    }

    /**
     * 统计总体数据
     * @param contractOfThisYear 签署的合同
     */
    private Map<String, TreeMap<String, Map<String, BigDecimal>>> staticsByTotal(List<TRbhetong0DTO> contractOfThisYear) {
        Map<String, TreeMap<String, Map<String, BigDecimal>>> result = new HashMap<>();
        TreeMap<String, Map<String, BigDecimal>> withTax = new TreeMap<>();
        TreeMap<String, Map<String, BigDecimal>> withOutTax = new TreeMap<>();
        // 合同数据按照合同生效日期分组
        Map<Integer, List<TRbhetong0DTO>> monthGroup = contractOfThisYear.stream().collect(Collectors.groupingBy(contract -> DateUtil.month(contract.getHetongshengxiaoriqi())));
        // 当前月份
        int currentMonth = DateUtil.month(new Date());
        for(int i = 0; i<= currentMonth; i++){
            // 不含税数据
            Map<String, BigDecimal> dataMapWithoutTax = new HashMap<>();
            // 含税数据
            Map<String, BigDecimal> dataMapWithTax = new HashMap<>();
            // 显示月份
            int monthNo = i + 1;
            // 判断按月份分组的数据集合中是否包含 i
            if(!monthGroup.containsKey(i)){
                dataMapWithTax.put("totalAmountWithTax", BigDecimal.ZERO);
//                dataMapWithTax.put("totalAmountOfNotSaleWithTax", BigDecimal.ZERO);
                dataMapWithTax.put("totalAmountOfSaleAutonomyWithTax", BigDecimal.ZERO);
                dataMapWithTax.put("totalAmountOfSaleUndertakeWithTax", BigDecimal.ZERO);
                withTax.put(monthNo + "", dataMapWithTax);


                dataMapWithoutTax.put("totalAmountWithoutTax", BigDecimal.ZERO);
//                dataMapWithoutTax.put("totalAmountOfNotSaleWithoutTax", BigDecimal.ZERO);
                dataMapWithoutTax.put("totalAmountOfSaleAutonomyWithoutTax", BigDecimal.ZERO);
                dataMapWithoutTax.put("totalAmountOfSaleUndertakeWithoutTax", BigDecimal.ZERO);
                withOutTax.put(monthNo + "", dataMapWithoutTax);
                continue;
            }
            // 取出第 i 个月的数据
            List<TRbhetong0DTO> contractOfThisMonth = monthGroup.get(i);
//            // 销售部门下的合同
//            List<TRbhetong0DTO> contractOfSale = new ArrayList<>();
//            // 非销售部门下的合同
//            List<TRbhetong0DTO> contractOfNotSale = new ArrayList<>();
//            // 根部门
//            Department dept = Application.getUserStore().getDepartment(DepartmentService.ROOT_DEPT);
//            // 坐在部门的所有子部门(包括自己)
//            Set<BusinessUnit> units = dept.getAllChildrenModified();
//            // 查询销售中心及子部门
//            BusinessUnit bn = units.stream().filter(unit -> unit.getName().equalsIgnoreCase("销售中心")).findAny().orElse(null);
//            if(Objects.nonNull(bn)){
//                Set<BusinessUnit> grandSons = bn.getChildren();
//                List<String> grandSonIds = grandSons.stream().map(BusinessUnit::getIdentity).map(Serializable::toString).collect(Collectors.toList());
//                grandSonIds.add(bn.getIdentity().toString());
//                log.info("销售中心下的部门(包括销售中心)分别是：{}", grandSonIds);
//                // 销售部门下的合同
//                contractOfSale = contractOfThisMonth.stream().filter(unit -> grandSonIds.contains(unit.getOwningDept())).collect(Collectors.toList());
//                // 非销售部门下的合同
//                contractOfNotSale = contractOfThisMonth.stream().filter(unit -> !grandSonIds.contains(unit.getOwningDept())).collect(Collectors.toList());
//            }

//            // 3. 签约总金额（含税）-非销售
//            BigDecimal totalAmountOfNotSaleWithTax = contractOfThisMonth.stream().map(TRbhetong0DTO::getQianyuejine).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 4. 签约总金额（未税）-非销售
            BigDecimal totalAmountOfNotSaleWithoutTax = contractOfThisMonth.stream().map(TRbhetong0DTO::getQianyuejineweishui).reduce(BigDecimal.ZERO, BigDecimal::add);
//            // 5. 签约总金额（含税）-销售-自主交付模式
//            BigDecimal totalAmountOfSaleAutonomyWithTax = contractOfThisMonth.stream().filter(unit -> unit.getJuesedandangName().equals("自主")).map(TRbhetong0DTO::getQianyuejine).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 6. 签约总金额（未税）-销售-自主交付模式
            BigDecimal totalAmountOfSaleAutonomyWithoutTax = contractOfThisMonth.stream().filter(unit -> unit.getJuesedandangName().equals("自主")).map(TRbhetong0DTO::getQianyuejineweishui).reduce(BigDecimal.ZERO, BigDecimal::add);
//            // 7. 签约总金额（含税）-销售-承接交付模式
//            BigDecimal totalAmountOfSaleUndertakeWithTax = contractOfThisMonth.stream().filter(unit -> unit.getJuesedandangName().equals("承接")).map(TRbhetong0DTO::getQianyuejine).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 8. 签约总金额（未税）-销售-承接交付模式
            BigDecimal totalAmountOfSaleUndertakeWithoutTax = contractOfThisMonth.stream().filter(unit -> unit.getJuesedandangName().equals("承接")).map(TRbhetong0DTO::getQianyuejineweishui).reduce(BigDecimal.ZERO, BigDecimal::add);
//            // 1. 签约总金额（含税）
//            BigDecimal totalAmountWithTax = NumberUtil.add(totalAmountOfSaleAutonomyWithTax, totalAmountOfSaleUndertakeWithTax);
            // 2. 签约总金额（未税）
            BigDecimal totalAmountWithoutTax = NumberUtil.add(totalAmountOfSaleAutonomyWithoutTax, totalAmountOfSaleUndertakeWithoutTax);

//            dataMapWithTax.put("totalAmountWithTax", totalAmountWithTax);
//            dataMapWithTax.put("totalAmountOfSaleAutonomyWithTax", totalAmountOfSaleAutonomyWithTax);
//            dataMapWithTax.put("totalAmountOfSaleUndertakeWithTax", totalAmountOfSaleUndertakeWithTax);
//            withTax.put(monthNo + "", dataMapWithTax);


            dataMapWithoutTax.put("totalAmountWithoutTax", totalAmountWithoutTax);
            dataMapWithoutTax.put("totalAmountOfNotSaleWithoutTax", totalAmountOfNotSaleWithoutTax);
            dataMapWithoutTax.put("totalAmountOfSaleAutonomyWithoutTax", totalAmountOfSaleAutonomyWithoutTax);
            dataMapWithoutTax.put("totalAmountOfSaleUndertakeWithoutTax", totalAmountOfSaleUndertakeWithoutTax);
            withOutTax.put(monthNo + "", dataMapWithoutTax);
        }
        result.put("withTax", withTax);
        result.put("withOutTax", withOutTax);
        return result;
    }

    /**
     * 查询今年的合同数据
     * @return
     */
    private List<TRbhetong0DTO> thisYearContract() {
        DateTime thisYear = DateUtil.date();
        int year = thisYear.year();
        // 查询本年度生效的销售合同
        return getContractByQianyueshijian(year + "");
    }

    /**
     * 根据签约时间查询合同
     * @param year
     * @return
     */
    private List<TRbhetong0DTO> getContractByQianyueshijian(String year) {
        QueryWrapper<TRbhetong0DTO> query = new QueryWrapper<>();
        query.apply(" year(hetongshengxiaoriqi) = " + year);
        return tRbhetong0Mapper.selectList(query);
    }

    /**
     * 根据部门名称查询department信息
     * @param deptName
     * @return
     */
    private Department getByDeptName(String deptName){
        // 所有部门
        Set<BusinessUnit> allDept = Application.getUserStore().getDepartment(DepartmentService.ROOT_DEPT).getAllChildrenModified();
        BusinessUnit bu = allDept.stream().filter(b -> b.getName().equalsIgnoreCase(deptName)).findAny().orElse(null);
        if(Objects.isNull(bu)){
            return null;
        }
        return (Department) bu;
    }

    /**
     * 需要展示统计数据的部门
     * @return
     */
    private List<BusinessUnit> deptToShow(){
        List<BusinessUnit> result = new ArrayList<>();
        // 合同统计部门
        List<String> deptList = Arrays.asList(deptListStr.split(","));
        for(String deptName : deptList){
            Department parentBU = getByDeptName(deptName);
            if(Objects.nonNull(parentBU)){
                result.add(parentBU);
            }
        }
        return result;
    }
}
